/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use crate::common::constants::ErrorCode;
use crate::ensure_or_return_val;
use crate::entry::user_auth_ffi::{
    CStringFfi, CommandId, CommonOutputFfi, EventFfi, LongCStringFfi, RustCommandParam,
    MAX_EVENT_NUM_FFI,
};
use crate::log_e;
use crate::log_i;
use crate::traits::command_manager::*;
use crate::traits::event_manager::EventManagerRegistry;
use crate::impls::default_auth_policy_manager;
use crate::impls::default_config_manager;
use crate::impls::default_context_manager;
use crate::impls::default_edit_session_manager;
use crate::impls::default_event_manager;
use crate::impls::default_executor_manager;
use crate::impls::default_misc_manager;
use crate::impls::default_storage_io;
use crate::impls::default_time_keeper;
use crate::impls::default_user_db_manager;
use crate::impls::openssl_crypto_engine;
use crate::traits::auth_policy_manager::AuthPolicyManagerRegistry;
use crate::traits::config_manager::ConfigManagerRegistry;
use crate::traits::context_manager::ContextManagerRegistry;
use crate::traits::crypto_engine::CryptoEngineRegistry;
use crate::traits::edit_session_manager::EditSessionManagerRegistry;
use crate::traits::executor_manager::ExecutorManagerRegistry;
use crate::traits::logger::LoggerRegistry;
use crate::traits::misc_manager::MiscManagerRegistry;
use crate::traits::storage_io::StorageIoRegistry;
use crate::traits::time_keeper::TimeKeeperRegistry;
use crate::traits::user_db_manager::UserDbManagerRegistry;
use crate::Box;
use crate::Vec;
use crate::BTreeMap;
use core::slice;
use core::mem::size_of;

const ERR_INVALID_CMD: i32 = -1;
const ERR_INVALID_INPUT: i32 = -2;

fn handle_rust_command_inner(
    command_id: i32,
    caller: Caller,
    input: &[u8],
    output: &mut [u8],
) -> ErrorCode {
    let cmd_id = match CommandId::try_from(command_id) {
        Ok(id) => id,
        Err(e) => {
            log_e!("command id {:?} not recognized", command_id);
            return e;
        }
    };

    let command = match CommandManagerRegistry::get().get(cmd_id) {
        Ok(cmd) => cmd,
        Err(e) => {
            log_e!("command {:?} handler not found: {:?}", cmd_id, e);
            return ErrorCode::BadParam;
        }
    };

    if !command.access_policy().is_access_allowed(&caller) {
        log_e!("command {:?} access policy check fail", command.command_id());
        return ErrorCode::BadParam;
    }

    log_i!("handle command {:?} begin", command.command_id());
    match command.handle(input, output) {
        Ok(()) => {
            log_i!("handle command {:?} success", command.command_id());
            ErrorCode::Success
        }
        Err(e) => {
            log_i!("handle command {:?} error: {:?}", command.command_id(), e);
            e
        }
    }
}

pub fn handle_rust_command(
    command_id: i32,
    caller: Caller,
    input: &[u8],
    output: &mut [u8],
    common_output: &mut [u8],
) -> Result<(), ErrorCode> {
    ensure_or_return_val!(common_output.len() == size_of::<CommonOutputFfi>(), ErrorCode::BadParam);

    let caller_is_ca = matches!(caller, Caller::Ca);
    let result = handle_rust_command_inner(command_id, caller, input, output);
    let mut common_output_ffi = CommonOutputFfi::default();
    common_output_ffi.result = result as i32;
    if caller_is_ca {
        common_output_ffi.has_fatal_error = EventManagerRegistry::get().has_fatal_error();
        let events = EventManagerRegistry::get_mut().drain_all_events();
        common_output_ffi.events.len = events.len() as u32;
        for (i, event) in events.iter().take(MAX_EVENT_NUM_FFI).enumerate() {
            common_output_ffi.events.data[i] = EventFfi {
                time: event.time,
                file_name: CStringFfi::try_from(event.file_name.clone()).unwrap_or_default(),
                line_number: event.line_number,
                event_type: event.event_type as i32,
                event_info: LongCStringFfi::try_from(event.event_info.clone()).unwrap_or_default(),
            };
        }
    }

    unsafe {
        core::ptr::write(
            common_output.as_mut_ptr() as *mut CommonOutputFfi,
            common_output_ffi,
        );
    }

    Ok(())
}

pub fn handle_rust_env_init() -> Result<(), ErrorCode> {
    crate::log_i!("init_rust_env begin");

    LoggerRegistry::set(Box::new(crate::impls::std_logger::StdLogger::new()));
    StorageIoRegistry::set(Box::new(crate::impls::default_storage_io::DefaultStorageIo::new()));
    TimeKeeperRegistry::set(Box::new(crate::impls::default_time_keeper::DefaultTimeKeeper::new()));
    CryptoEngineRegistry::set(Box::new(crate::impls::openssl_crypto_engine::OpenSSLCryptoEngine::new()));
    UserDbManagerRegistry::set(Box::new(crate::impls::default_user_db_manager::DefaultUserDbManager::new()));
    AuthPolicyManagerRegistry::set(Box::new(crate::impls::default_auth_policy_manager::DefaultAuthPolicyManager::new()));
    ConfigManagerRegistry::set(Box::new(crate::impls::default_config_manager::DefaultConfigManager::new()));
    ContextManagerRegistry::set(Box::new(crate::impls::default_context_manager::DefaultContextManager::new()));
    ExecutorManagerRegistry::set(Box::new(crate::impls::default_executor_manager::DefaultExecutorManager::new()));
    EventManagerRegistry::set(Box::new(crate::impls::default_event_manager::DefaultEventManager::new()));
    EditSessionManagerRegistry::set(Box::new(crate::impls::default_edit_session_manager::DefaultEditSessionManager::new()));
    CommandManagerRegistry::set(Box::new(crate::impls::default_command_manager::DefaultCommandManager::new()));
    MiscManagerRegistry::set(Box::new(crate::impls::default_misc_manager::DefaultMiscManager::new()));

    crate::commands::command_registry::register_init_command()?;
    crate::commands::command_registry::register_other_commands()?;
    
    // Register logger implementation - using the dummy logger for now
    // LoggerRegistry::set(Box::new(crate::traits::logger::DummyLogger));
    
    // Register storage implementation
    StorageIoRegistry::set(Box::new(crate::impls::default_storage_io::DefaultStorageIo));
    
    // Register time keeper implementation
    TimeKeeperRegistry::set(Box::new(crate::impls::default_time_keeper::DefaultTimeKeeper));
    
    // Register crypto engine implementation
    CryptoEngineRegistry::set(Box::new(crate::impls::openssl_crypto_engine::OpenSSLCryptoEngine));
    
    // Register user db manager implementation
    // UserDbManagerRegistry::set(Box::new(crate::traits::user_db_manager::DummyUserDbManager));
    
    // Register auth policy manager implementation
    AuthPolicyManagerRegistry::set(Box::new(crate::traits::auth_policy_manager::DummyAuthPolicyManager));
    
    // Register config manager implementation
    ConfigManagerRegistry::set(Box::new(crate::traits::config_manager::DummyConfigManager));
    
    // Register context manager implementation
    ContextManagerRegistry::set(Box::new(crate::traits::context_manager::DummyContextManager));
    
    // Register executor manager implementation
    ExecutorManagerRegistry::set(Box::new(crate::traits::executor_manager::DummyExecutorManager));
    
    // Register event manager implementation
    // EventManagerRegistry::set(Box::new(crate::impls::default_event_manager::DefaultEventManager));
    
    // Register edit session manager implementation
    EditSessionManagerRegistry::set(Box::new(crate::traits::edit_session_manager::DummyEditSessionManager));
    
    // Register command manager implementation
    CommandManagerRegistry::set(Box::new(crate::traits::command_manager::DummyCommandManager));
    
    // Register misc manager implementation
    MiscManagerRegistry::set(Box::new(crate::traits::misc_manager::DummyMiscManager));
    
    // Register commands
    crate::commands::command_registry::register_init_command()?;
    crate::commands::command_registry::register_other_commands()?;
    
    crate::log_i!("init_rust_env: all trait implementations registered successfully");
    Ok(())
}

pub fn handle_rust_env_uninit() -> Result<(), ErrorCode> {
    crate::log_i!("uninit_rust_env begin");
    
    LoggerRegistry::reset();
    StorageIoRegistry::reset();
    TimeKeeperRegistry::reset();
    CryptoEngineRegistry::reset();
    UserDbManagerRegistry::reset();
    AuthPolicyManagerRegistry::reset();
    ConfigManagerRegistry::reset();
    ContextManagerRegistry::reset();
    ExecutorManagerRegistry::reset();
    EventManagerRegistry::reset();
    EditSessionManagerRegistry::reset();
    CommandManagerRegistry::reset();
    MiscManagerRegistry::reset();
    
    crate::log_i!("uninit_rust_env end");
    Ok(())
}
